from abc import ABC, abstractmethod
import threading
from collections.abc import Callable

class StrategyBase(ABC):
    """Strategy base class"""

    def __init__(self) -> None:
        self.event = threading.Event()
        self.name = self.__class__.__name__
        self._is_finished = False
        self._lock = threading.Lock()
    
    @abstractmethod
    def execute(self, id: int):
        """
        Execute the strategy with the instance id.
        """
        raise NotImplementedError

    @abstractmethod
    def stop(self) -> None:
        raise NotImplementedError
    
    def is_finished(self) -> bool:
        with self._lock:
            return self._is_finished


def general_L0_strategy(fault_code: int, id: int) -> type[StrategyBase] | None:
    "L0 means healthy, so no strategy is needed."
    return None

def general_L1_strategy(fault_code: int, id: int) -> type[StrategyBase] | None:
    return None

def specific_L2_strategy(fault_code: int, id: int) -> type[StrategyBase] | None:
    # Only handle whitelisted fault codes for L2 strategy
    if fault_code in [0x00f1fef5, 0x08520003]:
        from motor.controller.ft.strategy.lingqu_network_recover import LingquNetworkRecoverStrategy
        return LingquNetworkRecoverStrategy
    else:
        return None

def general_L3_to_L6_strategy(fault_code: int, id: int) -> type[StrategyBase]:
    from motor.controller.core.instance_manager import InstanceManager
    from motor.controller.ft.strategy.scale_p2d import ScaleP2DStrategy
    instance = InstanceManager().get_instance(id)
    if instance is not None and instance.role == "decode":
        return ScaleP2DStrategy
    else:
        return None
    
def generate_strategy_map() -> dict[str, Callable[[int], type[StrategyBase] | None] | None]:
    return {
        "L0": general_L0_strategy,
        "L1": general_L1_strategy,
        "L2": specific_L2_strategy,
        "L3": general_L3_to_L6_strategy,
        "L4": general_L3_to_L6_strategy,
        "L5": general_L3_to_L6_strategy,
        "L6": general_L3_to_L6_strategy,
    }